/************** O T T R   C O P Y R I G H T   N O T I C E **************
 **                                                                   **
 ** © 2013 OTTR, Inc.  All rights reserved.                           **
 **                                                                   ** 
 *************** O T T R   C O P Y R I G H T   N O T I C E *************/

package com.jonathan.jtar;

import java.io.EOFException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;

/**
 *
 * @author Jonathan Paz <jonathan.paz@ottr.com>
 */
public class TarInputStream extends FilterInputStream {
    private static final Logger LOG = Logger.getLogger(TarInputStream.class.getName());
    protected byte[] buf;
    private final byte[] single = new byte[1];
    private final byte[] temp = new byte[512];
    private boolean closed = false;
    private long remaining;
    private boolean endEntry;
    int pos,buflen;

    public TarInputStream(InputStream in) {
        this(in, 10240);
    }

    public TarInputStream(InputStream in, int size) throws IllegalArgumentException {
        super(in);
        if ((size % 512) != 0) {
            throw new IllegalArgumentException("Size must be a multiple of 512");
        }
        buf = new byte[size];
    }


    @Override
    public int read() throws IOException {
        ensureOpen();
        int ct = read(single,0,1);
        if (ct == -1) {
            return -1;
        }
        return single[0] & 0x00ff;
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        ensureOpen();
        if (remaining <= 0) {
            return -1;
        }
        if (len > remaining) {
            len = (int)remaining;
        }
        int total = 0;
        while (len > (buflen - pos)) {
            System.arraycopy(buf, pos, b, off, buflen - pos);
            total += buflen - pos;
            len -= buflen - pos;
            off += buflen - pos;
            fill();
        }
        System.arraycopy(buf, pos, b, off, len);
        pos -= len;
        return total;
    }

    @Override
    public long skip(long n) throws IOException {
        ensureOpen();
        return super.skip(n); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public int available() throws IOException {
        ensureOpen();
        return buflen - pos;
    }

    @Override
    public void close() throws IOException {
        in.close();
        closed = true;
    }

    @Override
    public synchronized void mark(int readlimit) {
    }

    @Override
    public synchronized void reset() throws IOException {

    }

    @Override
    public boolean markSupported() {
        return false;
    }

    protected void fill() throws IOException {
        if (pos >= buflen) {
            buflen = in.read(buf,0,buf.length);
            if (buflen == -1) {
                throw new EOFException("Unexpected end of input stream");
            }
            if ((buflen % 512) != 0) {
                throw new IOException("Could not read a full record");
            }
            pos = 0;
        }
    }

    @SuppressWarnings("empty-statement")
    public void closeEntry() throws IOException {
        while ((read(temp,0,temp.length)) != -1);
        endEntry = true;
    }

    public TarEntry getNextEntry() throws IOException {
        closeEntry();
        return null;
    }

    private void ensureOpen() throws IOException {
        if (closed) {
            throw new IOException("The stream is closed");
        }
    }
}
